﻿
#include "stdafx.h"
#include "colordef.h"
#include "alpha_x86.inl"
#include "alpha_mmx.inl"

//////////////////////////////////////////////////////////////////////////

VOID CCALL AlphaBlendFullLevelMMX(WORD src, LPVOID dest, UINT pitch, UINT cx, UINT cy, BYTE alpha)
{
	LPBYTE line = static_cast<LPBYTE>(dest);

	for (; cy; cy--, line += pitch)
	{
		LPWORD img = reinterpret_cast<LPWORD>(line);

		for (UINT i = cx; i; i--, img++)
			AlphaBlendFullLevelMMX(&src, img, &alpha);
	}
}

VOID CCALL AlphaBlend32LevelMMX(WORD src, LPVOID dest, UINT pitch, UINT cx, UINT cy, BYTE alpha)
{
	static const QWORD COLORMASK = 0x07e0f81f07e0f81f;

	LPBYTE line = static_cast<LPBYTE>(dest);
	BYTE alpha_p[] = { alpha, alpha, alpha, alpha };
	WORD src_p[] = { src, src, src, src };

	__asm
	{
		movq		mm4, COLORMASK
	}

	UINT loop = cx >> 1;

	if (cx & 0x1)
	{
		for (; cy; cy--, line += pitch)
		{
			LPWORD img = reinterpret_cast<LPWORD>(line);

			for (UINT i = loop; i; i--, img += 2)
				AlphaBlend32LevelMMX(src_p, img, alpha_p);

			AlphaBlend32LevelX86(src_p, img, alpha_p);
		}
	}
	else
	{
		for (; cy; cy--, line += pitch)
		{
			LPWORD img = reinterpret_cast<LPWORD>(line);

			for (UINT i = loop; i; i --, img += 2)
				AlphaBlend32LevelMMX(src_p, img, alpha_p);
		}
	}

	__asm emms
}

VOID CCALL AlphaBlend32LevelMMX(LPCVOID src, UINT src_pitch, LPVOID dest, UINT dest_pitch, LPCVOID alpha, UINT alpha_pitch, UINT cx, UINT cy)
{
	static const QWORD COLORMASK = 0x07e0f81f07e0f81f;

	LPCBYTE src_ln = static_cast<LPCBYTE>(src);
	LPBYTE dest_ln = static_cast<LPBYTE>(dest);
	LPCBYTE alpha_ln = static_cast<LPCBYTE>(alpha);

	__asm
	{
		movq		mm4, COLORMASK
	}

	UINT loop = cx >> 1;

	if (cx & 0x1)
	{
		for (; cy; cy--, src_ln += src_pitch, dest_ln += dest_pitch, alpha_ln += alpha_pitch)
		{
			LPCWORD src_ptr = reinterpret_cast<LPCWORD>(src_ln);
			LPWORD dest_ptr = reinterpret_cast<LPWORD>(dest_ln);
			LPCBYTE alpha_ptr = alpha_ln;

			for (UINT i = loop; i; i--, src_ptr += 2, dest_ptr += 2, alpha_ptr += 2)
				AlphaBlend32LevelMMX(src_ptr, dest_ptr, alpha_ptr);

			AlphaBlend32LevelX86(src_ptr, dest_ptr, alpha_ptr);
		}
	}
	else
	{
		for (; cy; cy--, src_ln += src_pitch, dest_ln += dest_pitch, alpha_ln += alpha_pitch)
		{
			LPCWORD src_ptr = reinterpret_cast<LPCWORD>(src_ln);
			LPWORD dest_ptr = reinterpret_cast<LPWORD>(dest_ln);
			LPCBYTE alpha_ptr = alpha_ln;

			for (UINT i = loop; i; i--, src_ptr += 2, dest_ptr += 2, alpha_ptr += 2)
				AlphaBlend32LevelMMX(src_ptr, dest_ptr, alpha_ptr);
		}
	}

	__asm emms
}

//////////////////////////////////////////////////////////////////////////
